package entity

import (
	"src/zeus/iserver"
	"src/zeus/logger"
	"src/zeus/msgdef"
	"src/zeus/serializer"
	"src/zeus/sess"
	"strconv"
)

type EntitiesMsgProc struct {
	iserver.IEntities
}

/*
目前设计只用于群发给不同客户端的用户
场景根据条件广播消息
*/
func (es *EntitiesMsgProc) MsgProc_EntitysMsgTransport(msg *msgdef.EntitysMsgTransport) {
	if msg.SrvType != iserver.ServerTypeClient {
		//目前设计只用于发消息给客户端
		return
	}
	// logger.Debugf(logger.LogKey_Default, "EntitiesMsgProc.MsgProc_EntitysMsgTransport %p", msg)
	for i := range msg.EntityID {
		ie := es.GetEntity(msg.EntityID[i])
		if ie == nil {
			continue
		}
		te := ie.(iEntityCtrl)
		if clientSess := te.GetClientSess(); clientSess != nil {
			// logger.Debug("EntityMsgTransport to Client.")
			clientSess.SendRaw(msg.MsgContent)
		} else {
			logger.Debug(logger.LogKey_Entity, "EntitysMsgTransport to Client failed, UserSess is nil. Is THIS Srv Gateway ??? ")
		}
	}
}

// MsgProc_EntityMsgTransport Entity之间转发消息
func (es *EntitiesMsgProc) MsgProc_EntityMsgTransport(msg *msgdef.EntityMsgTransport) {
	ie := es.GetEntity(msg.EntityID)
	if ie == nil {
		return
	}

	te := ie.(iEntityCtrl)
	if msg.SrvType == iserver.ServerTypeClient {
		if clientSess := te.GetClientSess(); clientSess != nil {
			// logger.Debug("EntityMsgTransport to Client.")
			clientSess.SendRaw(msg.MsgContent)
		} else {
			logger.Debug(logger.LogKey_Entity, "EntityMsgTransport to Client failed, UserSess is nil. Is THIS Srv Gateway ??? ")
		}
	} else {
		innerMsg, err := sess.DecodeMsg(msg.MsgContent[3], msg.MsgContent[4:])
		if err != nil {
			logger.Error("Decode innerMsg failed", err, msg)
			return
		}

		if !iserver.GetSrvInst().IsSrvValid() {
			iserver.GetSrvInst().HandlerSrvInvalid(ie.GetID())
		} else {
			// logger.Debug("EntityMsgTransport:", innerMsg.Name())
			te.FireMsg(innerMsg.Name(), innerMsg)
		}
	}
}

// MsgProc_CreateEntityReq 请求创建Entity
func (es *EntitiesMsgProc) MsgProc_CreateEntityReq(msg *msgdef.CreateEntityReq) {
	// modify by zgb 2021/08/02
	//cpu的空闲判断，在gate上获取服务器ID的时候就已经判断过了，这里不应该再判断，增加逻辑的复杂性,
	//正确的做法应该是当gate上判断，可以完善gate上负载均衡的逻辑和监控

	// maxLoad := viper.GetInt("Config.MaxLoad")
	// if maxLoad != 0 {
	// 	load := iserver.GetSrvInst().GetLoad()
	// 	if load > maxLoad {
	// 		log.Warnf("Overload Current:%d MaxLoad:%d Msg:%s", load, maxLoad, content)
	// 		return
	// 	}
	// }
	params := serializer.UnSerialize(msg.InitParam)
	if len(params) != 1 {
		logger.Error("Init param error ", params)
		return
	}
	_, err := es.CreateEntity(msg.EntityType, msg.EntityID, msg.DBID, 0, params[0], false, false)
	if err != nil {
		logger.Error("Create entity failed ", err, msg)
	} else {
		msgRet := &msgdef.CreateEntityRet{
			EntityID:   msg.EntityID,
			SrvType:    iserver.GetSrvInst().GetSrvType(),
			SrvID:      iserver.GetSrvInst().GetSrvID(),
			CallbackID: 0,
			ErrorStr:   "",
		}

		if err := iserver.GetSrvInst().PostMsgToSpace(msg.SrcSrvID, 0, msgRet); err != nil {
			logger.Error(err)
		}
	}
}

// MsgProc_CreateEntityRet 请求创建Entity返回
func (es *EntitiesMsgProc) MsgProc_CreateEntityRet(msg *msgdef.CreateEntityRet) {
	e := es.GetEntity(msg.EntityID)
	if e == nil {
		return
	}
	e.GetEntitySrvID(msg.SrvType)
	if es.GetTypeIsInRegMap(msg.SrvType) {
		es.RegEntityGroup(strconv.FormatUint(msg.SrvID, 10), e)
	}
}

// MsgProc_DestroyEntityReq 请求删除Entity
func (es *EntitiesMsgProc) MsgProc_DestroyEntityReq(msg *msgdef.DestroyEntityReq) {
	err := es.DestroyEntity(msg.EntityID)
	if err != nil {
		return
		// logger.Error("Delete entity failed ", err, msg)
	} else {
		msgRet := &msgdef.DestroyEntityRet{
			EntityID:   msg.EntityID,
			SrvType:    iserver.GetSrvInst().GetSrvType(),
			SrvID:      iserver.GetSrvInst().GetSrvID(),
			CallbackID: 0,
			ErrorStr:   "",
			TarSrvID:   msg.TarSrvID,
		}

		if err := iserver.GetSrvInst().PostMsgToSpace(msg.SrcSrvID, 0, msgRet); err != nil {
			logger.Error(err)
		}
	}
}

// DestroyEntityRet 请求删除Entity返回
func (es *EntitiesMsgProc) MsgProc_DestroyEntityRet(msg *msgdef.DestroyEntityRet) {
	e := es.GetEntity(msg.EntityID)
	if e == nil {
		return
	}
	if es.GetTypeIsInRegMap(msg.SrvType) {
		es.UnRegEntityGroup(strconv.FormatUint(msg.SrvID, 10), e)
	}
	if msg.TarSrvID != 0 {
		// 创建tar中的entity
		msgRt := &msgdef.CreateEntityReq{
			EntityType: e.GetType(),
			EntityID:   msg.EntityID,
			SpaceID:    0,
			InitParam:  serializer.Serialize(e.GetInitParam()),
			DBID:       e.GetDBID(),
			SrcSrvType: iserver.GetSrvInst().GetSrvType(),
			SrcSrvID:   iserver.GetSrvInst().GetSrvID(),
			CallbackID: 0,
		}

		if err := iserver.GetSrvInst().PostMsgToSpace(msg.TarSrvID, 0, msgRt); err != nil {
			logger.Error(err)
			return
		}
	}
}
func (es *EntitiesMsgProc) MsgProc_SrvMsgTransport(msg *msgdef.SrvMsgTransport) {
	innerMsg, err := sess.DecodeMsg(msg.MsgContent[3], msg.MsgContent[4:])

	if err != nil {
		logger.Error(err, "msg", sess.GetMsgID(msg.MsgContent[4:]))
		return
	}

	es.GetMsgHandler().FireMsg(innerMsg.Name(), innerMsg)
}

// 把分组消息投递到一个服务器里
func (es *EntitiesMsgProc) MsgProc_SrvGroupMsgTransport(msg *msgdef.SrvGroupMsgTransport) {
	es.TravsalEntityByGroup(msg.Group, func(e iserver.IEntity) {
		if msg.SrvType == iserver.ServerTypeClient {
			if sess := e.(iEntityCtrl).GetClientSess(); sess != nil {
				sess.SendRaw(msg.MsgContent)
			}
		} else {
			innerMsg, err := sess.DecodeMsg(msg.MsgContent[3], msg.MsgContent[4:])
			if err != nil {
				logger.Error("MsgProc_SrvGroupMsgTransport Decode innerMsg failed", err, msg)
				return
			}

			if !iserver.GetSrvInst().IsSrvValid() {
				iserver.GetSrvInst().HandlerSrvInvalid(e.GetID())
			} else {
				e.(iEntityCtrl).FireMsg(innerMsg.Name(), innerMsg)
			}
		}
	})

}
